<template>
  <view class="list-wrap">
    <slot name="list-top"></slot>
    <!-- @scrolltolower="loadmore" -->
    <scroll-view
      scroll-y
      @touchmove.stop="handleTouchMove"
      @scroll="handleScroll"
      :style="{
        'justify-content': isScrollerFlex ? 'flex-start' : 'flex-end',
      }"
      @click="chatListClick"
      ref="scrollerDom"
      id="scrollerDom"
      class="list"
      @scrolltoupper="handleScrollToTop"
      :loadmoreoffset="10"
      :scroll-top="scrollTop"
    >
      <!-- 用于定位到底部-->
      <div ref="rowTop"></div>
      <!-- <view v-if="finish" style="height: 60rpx"></view> -->
      <view class="cell">
        <view class="topzw" v-if="!finish">· · ·</view>
        <uni-load-more
          :iconSize="16"
          iconType="snow"
          :status="loadingStatus"
        ></uni-load-more>
      </view>

      <view ref="item" class="item-wrap">
        <view v-for="item in list" :key="item.id">
          <ChatItem
            :isError="item.isError"
            @retry="retryClick(item)"
            :showIsRead="showIsRead"
            :isRead="item.isRead"
            :time="item.time"
            :showTime="item.showTime"
            @leftAvatarClick="leftAvatarClick(item)"
            @rightAvatarClick="rightAvatarClick(item)"
            :loading="item.loading"
            :avatar="item.avatar"
            :right="item.right"
          >
            <ChatText v-if="item.type === 'text'" :data="item"></ChatText>
            <ChatSound
              v-else-if="item.type === 'sound'"
              :data="item"
            ></ChatSound>
            <ChatRedPacket
              @redPacketClick="redPacketClick(item)"
              v-else-if="item.type === 'red-packet'"
              :data="item"
            ></ChatRedPacket>
            <ChatImage
              :urls="images"
              v-else-if="item.type === 'image'"
              :data="item"
            ></ChatImage>
            <ChatVideo
              v-else-if="item.type === 'video'"
              :data="item"
            ></ChatVideo>
            <ChatOrder
              v-else-if="item.type === 'order'"
              :data="item"
            ></ChatOrder>
            <TemplateMsg
              v-else-if="item.type === 'template'"
              :data="item"
            ></TemplateMsg>
            <Goods v-else-if="item.type === 'product'" :data="item"></Goods>
            <Share v-else-if="item.type === 'share'" :data="item"></Share>
          </ChatItem>
        </view>
      </view>
    </scroll-view>
    <BottomInput
      class="bottom"
      :isSafeArea="isSafeArea"
      :menu="bottomMenu"
      :value="inputValue"
      @menuClick="menuClick"
      @keyboardHeightChange="keyboardHeightChange"
      ref="bottomInput"
      @sendMessage="sendMessage"
    >
      <template v-slot:input-top>
        <slot name="input-top"></slot>
      </template>
    </BottomInput>
    <view
      class="product"
      :style="{ bottom: pbottom + 'px' }"
      v-show="showProduct"
    >
      <view class="obody">
        <view class="oclose" @click="closeProduct">
          <image class="oclosepic" src="/static/img/close2.png"></image>
        </view>
        <view class="ol">
          <image class="pic" :src="product.pic" mode="aspectFill"></image>
        </view>
        <view class="or">
          <view class="on">
            {{ product.name }}
          </view>
          <view class="op">
            <view>￥{{ product.sell_price }}</view>
            <view
              class="sendp"
              :style="{ backgroundColor: t('color1') }"
              @click="sendProduct"
              >发送商品</view
            >
          </view>
        </view>
      </view>
    </view>
  </view>
</template>

<script>
import ChatItem from "./chat-item.vue";
import ChatText from "./msg-template/text.vue";
import ChatSound from "./msg-template/sound.vue";
import ChatRedPacket from "./msg-template/red-packet.vue";
import ChatImage from "./msg-template/image.vue";
import ChatVideo from "./msg-template/video.vue";
import ChatTime from "./msg-template/time.vue";
import ChatOrder from "./msg-template/order.vue";
import TemplateMsg from "./msg-template/template.vue";
import Goods from "./msg-template/goods.vue";
import Share from "./msg-template/share.vue";
import BottomInput from "./bottom-input/bottom-input.vue";
import moment from "../moment/min/moment.min.js";
var app = getApp();
export default {
  components: {
    ChatItem,
    ChatText,
    ChatSound,
    ChatRedPacket,
    ChatImage,
    ChatVideo,
    BottomInput,
    ChatOrder,
    TemplateMsg,
    Goods,
    Share,
    ChatTime,
  },
  props: {
    inputValue: String,
    list: {
      type: Array,
      default: () => [],
    },
    // 加载状态
    loadingStatus: String,
    // 数据加载完毕
    finish: Boolean,
    // 底部菜单
    bottomMenu: {
      type: Array,
      default: () => [],
    },
    // 是否显示已读、未读
    showIsRead: Boolean,
    // 是否使用安全安全区域
    isSafeArea: Boolean,
  },
  data() {
    return {
      isScrollerFlex: false,
      images: [],
      scrollTop: 0,
      scrollMoreTimer: null,
      isScrollingTop: false, // 添加滚动状态标识
      product: {
        // name: "悦黔水牛奶 甄选意大利地中海水牛 甘蔗菠萝喂养 0添加 配料只有生水牛乳和生牛乳生水牛乳和生牛乳生水牛乳和生牛乳",
        // pic: "https://hedashepin.oss-cn-guangzhou.aliyuncs.com/upload/3/20250121/3b9376fd66d08494acc5a043b30d67fb.jpg",
        // sell_price: 666,
      },
      pbottom: 50,
      showProduct: false,
    };
  },
  mounted() {
    uni.$on("sendMessagetoBottom", this.scrollerBottom);
    this.$nextTick(() => {
      const query = uni.createSelectorQuery().in(this);
      query
        .select(".bottom")
        .boundingClientRect((rect) => {
          if (rect) {
            this.pbottom = rect.height; // 存储高度
          }
        })
        .exec();
    });
    var prod = uni.getStorageSync("ChatData");
    if (prod) {
      this.getProduct(prod);
    }
  },
  beforeDestroy() {
    uni.$off("sendMessagetoBottom", this.scrollerBottom);
    clearTimeout(this.scrollMoreTimer);
    uni.setStorageSync("ChatData", null);
  },
  methods: {
    // 红包点击
    redPacketClick(item) {
      this.$emit("redPacketClick", item);
    },
    // 消息重试
    retryClick(item) {
      this.$emit("retryClick", item);
    },
    rightAvatarClick(item) {
      this.$emit("rightAvatarClick", item);
    },
    leftAvatarClick(item) {
      this.$emit("leftAvatarClick", item);
    },
    menuClick(item) {
      this.$emit("menuClick", item);
    },
    keyboardHeightChange(height) {
      setTimeout(() => {
        this.setIsScroller();
        this.scrollerBottom();
      }, 100);
    },

    // getScrollerDomH() {
    // 	return new Promise((resolve, reject) => {
    // 		this.$nextTick(() => {
    // 			dom.getComponentRect(this.$refs.scrollerDom, res => {
    // 				resolve(res.size.height)
    // 			})
    // 		})
    // 	})
    // },

    getScrollerDomH() {
      // return new Promise((resolve, reject) => {
      // 	this.$nextTick(() => {
      // 		// 使用 uni.createSelectorQuery() 查询节点
      // 		const query = uni.createSelectorQuery().in(this); // 指定当前组件作用域
      // 		query.select(this.$refs.scrollerDom ? '#scrollerDom' : null).boundingClientRect((res) => {
      // 			if (res) {
      // 				resolve(res.height); // 返回元素高度
      // 			} else {
      // 				reject(new Error('获取元素高度失败'));
      // 			}
      // 		}).exec(); // 必须调用 exec() 才会执行查询
      // 	});
      // });
      return new Promise((resolve) => {
        this.$nextTick(() => {
          setTimeout(() => {
            // 双重保险
            uni
              .createSelectorQuery()
              .in(this)
              .select(".list") // 或 this.$refs.scrollerDom
              .boundingClientRect((res) => {
                if (res) resolve(res.height);
                else console.error("元素未渲染完成", res);
              })
              .exec();
          }, 50); // 适当延迟
        });
      });
    },

    // setIsScroller() {
    // 	this.$nextTick(async () => {
    // 		this.scrollerDomH = await this.getScrollerDomH()

    // 		dom.getComponentRect(this.$refs.item, res => {
    // 			let listContentHeight = res.size.height

    // 			this.isScrollerFlex = (listContentHeight - this.scrollerDomH) > 0
    // 		})
    // 	})
    // },

    setIsScroller() {
      this.$nextTick(async () => {
        this.scrollerDomH = await this.getScrollerDomH();
        console.log("scrollerDomH:", this.scrollerDomH);
        // 使用 uni.createSelectorQuery() 替代 dom.getComponentRect
        const query = uni.createSelectorQuery().in(this);
        query
          .select(this.$refs.item ? this.$refs.item : ".item-wrap")
          .boundingClientRect((res) => {
            // console.log("setIsScroller:", res)
            if (res) {
              let listContentHeight = res.height; // 原 res.size.height 改为 res.height
              this.isScrollerFlex = listContentHeight - this.scrollerDomH > 0;
            }
          })
          .exec(); // 必须调用 exec() 执行查询
      });
    },

    // loadmore() {
    //   this.$emit("loadmore");
    // },

    handleScroll(e) {
      //console.log("handleScroll:", e.detail.scrollTop, this.scrollTop);
      if (e.detail.scrollTop <= 5 && !this.isScrollingTop) {
        console.log("已滚动到顶部");
        this.scrollerMore();
      }
      //监听滑动导致冲突bug
      //this.$refs.bottomInput.closeToolsBoxAndKeyboard();
    },

    handleTouchMove(e) {
      console.log("触屏滚动");
      this.$refs.bottomInput.closeToolsBoxAndKeyboard();
    },

    // 加载更多之后滚动预留继续加载高度
    scrollerMore() {
      // 设置状态防止重复触发
      this.isScrollingTop = true;
      // 清除之前的定时器
      clearTimeout(this.scrollMoreTimer);
      // 设置新的定时器
      this.scrollMoreTimer = setTimeout(() => {
        console.log("滚动完成");
        this.$emit("loadmore");
        this.scrollTop = 0.01;
        this.$nextTick(() => {
          this.scrollTop = 20;
          // 重置状态（添加延迟确保滚动完成）
          setTimeout(() => {
            this.isScrollingTop = false;
          }, 300);
        });
      }, 300); // 300ms防抖间隔
    },

    // 滚动到底部
    async scrollerBottom() {
      uni
        .createSelectorQuery()
        .in(this)
        .select("#scrollerDom")
        .boundingClientRect((scrollView) => {
          uni
            .createSelectorQuery()
            .in(this)
            .select("#scrollerDom")
            .fields(
              {
                size: true,
                scrollOffset: true,
                rect: true,
              },
              (res) => {
                // 计算滚动到底部的位置
                this.scrollTop = res.scrollHeight - scrollView.height;
              }
            )
            .exec();
        })
        .exec();
      //   this.$nextTick(() => {
      //     this.scrollTop = 999999; // 设置一个足够大的值
      //   });
    },

    // 滚动到顶部事件处理(不准确)
    handleScrollToTop() {
      //   console.log("已滚动到顶部,", this.scrollTop);
      //   this.$emit("loadmore");
    },

    // 滚动到顶部
    async scrollerTop() {
      this.scrollTop = 0;
      // 小程序需要强制触发更新
      // #ifdef MP-WEIXIN
      this.scrollTop = 0.01; // 确保值变化
      this.$nextTick(() => {
        this.scrollTop = 0;
      });
      // #endif
    },

    // 聊天列表点击，可以用于隐藏底部工具栏
    chatListClick() {
      this.$refs.bottomInput.closeToolsBoxAndKeyboard();
    },

    getProduct(data) {
      if (data) {
        if (data.type == "product") {
          this.showProduct = true;
          this.product.pic = data.pic;
          this.product.name = data.name;
          this.product.proid = data.proid;
          this.product.sell_price = data.sell_price;
          this.product.ptype = data.ptype;
        }
      }
    },

    sendMessage(options) {
      console.log(options);
      this.$emit("sendMessage", options);
      this.scrollerBottom();
    },
    closeProduct() {
      this.showProduct = false;
      uni.setStorageSync("ChatData", null);
    },
    sendProduct() {
      this.showProduct = false;
      this.$emit("sendMessage", {
        type: "product",
        content: this.product.name,
        extend: {
          pic: this.product.pic,
          sell_price: this.product.sell_price,
          proid: this.product.proid,
          ptype: this.product.ptype,
        },
      });
    },
  },
  watch: {
    list: {
      handler() {
        let images = [];
        // 追加图片数组
        this.list.forEach((item, idx) => {
          // 是否显示时间
          //   let preTime =
          //     idx - 1 === -1
          //       ? moment().valueOf()
          //       : this.list[idx - 1].time * 1000;
          //   let time = item.time * 1000;
          //   // 时间差大于2分钟，显示时间
          //   if (moment(preTime).diff(time, "minutes", true) > 2) {
          //     this.$set(item, "showTime", true);
          //   }
          if (item.type === "image") {
            images.push(item.content);
          }
        });
        this.images = images;
        // this.setIsScroller();
      },
      deep: true,
      immediate: true,
    },
  },
};
</script>

<style lang="scss" scoped>
.list-wrap {
  background-color: #dbdbdb;
  display: flex;
  flex-direction: column;
  height: 100vh;
  position: relative;

  .list {
    display: flex;
    flex: 1;
    overflow-y: auto;
    box-sizing: border-box;
  }

  .item-wrap {
    width: 100vw;
    display: flex;
    flex-direction: column;
    gap: 15rpx;
  }

  .cell {
    padding: 5px 0;
    .topzw {
      width: 100%;
      text-align: center;
      height: 20rpx;
    }
  }

  .bottom {
    height: auto;
    width: 100%;
    background: pink;
    position: sticky;
    bottom: 0;
    z-index: 10;
  }
  .product {
    width: 100%;
    position: absolute;
    padding: 0 20rpx;
    .obody {
      display: flex;
      gap: 10rpx;
      justify-content: center;
      background-color: #ffffff;
      border-radius: 16rpx;
      padding: 10rpx;
      width: 100%;
      direction: ltr;
      margin: 10px auto;
      position: relative;

      .oclose {
        height: 50rpx;
        width: 50rpx;
        text-align: center;
        position: absolute;
        right: 10rpx;
        border-radius: 50%;
        color: #fff;
        background: #dadada;
        display: flex;
        align-items: center;
        justify-content: center;
        .oclosepic {
          width: 30rpx;
          height: 30rpx;
        }
      }

      .ol {
        width: 150rpx;
        height: 150rpx;

        image {
          width: 150rpx;
          height: 100%;
          border-radius: 16rpx;
          margin: auto;
        }
      }

      .or {
        display: flex;
        flex-direction: column;
        justify-content: space-between;

        .on {
          font-size: 28rpx;
          text-wrap: wrap;
          display: -webkit-box;
          -webkit-box-orient: vertical;
          -webkit-line-clamp: 2;
          overflow: hidden;
          padding-right: 50rpx;
        }

        .op {
          font-size: 29rpx;
          color: #ff4246;
          display: flex;
          justify-content: space-between;
          align-items: center;
          .sendp {
            border-radius: 40rpx;
            color: #fff;
            padding: 0rpx 12rpx;
            background-color: #ff4246;
          }
        }
      }
    }
  }
}
</style>
